<?php
declare(strict_types=1);

namespace app\api\controller;

use think\Request;
use think\response\Json;
use think\facade\Config;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

/**
 * Token 控制器
 * 用于生成标准的 JWT（HS256）
 * 固定 Header：{"alg":"HS256","typ":"JWT"}
 */
class Token
{
    /**
     * 默认方法：返回接口说明
     * @param Request $request
     * @return Json
     */
    public function index(Request $request): Json
    {
        return json([
            'code' => 0,
            'msg'  => 'Token 控制器就绪，使用 POST /api/token/generate 生成 JWT（HS256）',
            'data' => [
                'header' => ['alg' => 'HS256', 'typ' => 'JWT'],
                'routes' => [
                    'GET /api/token',
                    'POST /api/token/generate'
                ]
            ]
        ]);
    }

    /**
     * 生成 JWT Token
     * 接收参数：user_id（可选）、username（可选）、role_id（可选）
     * 若未传参，将尝试从请求头 Authorization 的现有 token 中解析用户信息
     * @param Request $request
     * @return Json
     */
    public function generate(Request $request): Json
    {
        try {
            // 读取配置
            $cfg    = Config::get('jwt', []);
            $secret = (string)($cfg['secret'] ?? 'SUNFARI');
            $issuer = (string)($cfg['iss'] ?? 'thinkadmin');
            $expire = (int)($cfg['expire'] ?? 7200);

            // 获取入参
            $userId   = trim((string)$request->post('user_id', ''));
            $username = trim((string)$request->post('username', ''));
            $roleId   = trim((string)$request->post('role_id', ''));

            // 未提供完整参数时，尝试从现有 token 解析
            if ($userId === '' || $username === '' || $roleId === '') {
                $auth = $request->header('Authorization', '');
                $incomingToken = '';
                if ($auth !== '') {
                    $incomingToken = preg_replace('/^Bearer\s+/i', '', $auth);
                }
                if ($incomingToken === '') {
                    $incomingToken = (string)$request->param('token', '');
                }
                if ($incomingToken !== '') {
                    $parsed = null;

                    // 尝试使用项目已有的 TokenService（如存在）
                    try {
                        if (class_exists('app\\api\\service\\TokenService')) {
                            $parsed = \app\api\service\TokenService::verify($incomingToken);
                        }
                    } catch (\Throwable $e) {
                        // 忽略，进入 JWT 解码尝试
                    }

                    // 使用标准 JWT 解码尝试（密钥为配置中的 SUNFARI）
                    if (empty($parsed)) {
                        try {
                            $decoded = JWT::decode($incomingToken, new Key($secret, 'HS256'));
                            $parsed = (array)$decoded;
                        } catch (\Throwable $e) {
                            // 忽略
                        }
                    }

                    if (!empty($parsed)) {
                        $userId   = $userId   !== '' ? $userId   : (string)($parsed['user_id'] ?? '');
                        $username = $username !== '' ? $username : (string)($parsed['username'] ?? '');
                        $roleId   = $roleId   !== '' ? $roleId   : (string)($parsed['role_id'] ?? '');
                    }
                }
            }

            // 至少需要一个用户字段，否则直接报错
            if ($userId === '' && $username === '' && $roleId === '') {
                return json([
                    'code' => 400,
                    'msg'  => '缺少用户信息：请提供 user_id/username/role_id 中至少一项，或在请求头携带 Authorization: Bearer {token}',
                    'data' => null
                ], 400);
            }

            // 组装标准 Payload
            $now = time();
            $payload = [
                'iss'      => $issuer,
                'iat'      => $now,
                'nbf'      => $now,
                'exp'      => $now + $expire,
                'user_id'  => $userId,
                'username' => $username,
                'role_id'  => $roleId,
            ];

            // 固定 Header
            $headers = [
                'alg' => 'HS256',
                'typ' => 'JWT',
            ];

            // 签发 Token（HS256）
            $jwt = JWT::encode($payload, $secret, 'HS256', null, $headers);

            return json([
                'code' => 0,
                'msg'  => '生成成功',
                'data' => [
                    'token' => $jwt
                ]
            ]);
        } catch (\Throwable $e) {
            return json([
                'code' => 500,
                'msg'  => '生成失败：' . $e->getMessage(),
                'data' => null
            ], 500);
        }
    }
}
